#include <memory.h>
#include <interrupt.h>
#include <keyboard.h>
#include <ports.h>
#include <floppy.h>
#include <printThings.h>
#include <mytime.h>
#include <multitasking.h>

static long long unsigned int idt[256];

inline static void enableInterrupts(void) {
    __asm__ __volatile__("sti");
}

struct {
    unsigned short int limit;
    void* pointer;
} __attribute__((packed)) idtp = {
    .limit = 256 * 8 - 1,
    .pointer = idt,
};

void installInt(int i, unsigned long long base, unsigned int selektor, int flags) {
    idt[i] = base & 0xffff;
    idt[i] |= (selektor & 0xffff) << 16;
    idt[i] |= (flags & 0xffLL) << 40;
    idt[i] |= ((base >> 16) & 0xffff) << 48;
}

void handleInterrupt(struct cpuState* cpu) {
    if (cpu->intr <= 0x1f) {
        printf("Exception %d at %y\n\n", cpu->intr, cpu->eip);

        if (cpu->intr == 14)
            pageFaultException(cpu->error, cpu->eip);


        while (1) {}
    } else {
        if (cpu->intr == 32) {
            /*timer interrupt*/
        }

        if (cpu->intr == 33)
            handleKeyboardInterrupt();


        if (cpu->intr == 38)
            handleFloppyInterrupt();
    }
    outb(0x20, 0x20);
    outb(0xA0, 0x20);
}


void initInt(void) {
    //gdt zusammenbauen

    installInt(0,(unsigned long)intr_stub_0,0x8, 0x8e);
    installInt(1,(unsigned long)intr_stub_1,0x8, 0x8e);
    installInt(2,(unsigned long)intr_stub_2,0x8, 0x8e);
    installInt(3,(unsigned long)intr_stub_3,0x8, 0x8e);
    installInt(4,(unsigned long)intr_stub_4,0x8, 0x8e);
    installInt(5,(unsigned long)intr_stub_5,0x8, 0x8e);
    installInt(6,(unsigned long)intr_stub_6,0x8, 0x8e);
    installInt(7,(unsigned long)intr_stub_7,0x8, 0x8e);
    installInt(8,(unsigned long)intr_stub_8,0x8, 0x8e);
    installInt(9,(unsigned long)intr_stub_9,0x8, 0x8e);
    installInt(10,(unsigned long)intr_stub_10,0x8, 0x8e);
    installInt(11,(unsigned long)intr_stub_11,0x8, 0x8e);
    installInt(12,(unsigned long)intr_stub_12,0x8, 0x8e);
    installInt(13,(unsigned long)intr_stub_13,0x8, 0x8e);
    installInt(14,(unsigned long)intr_stub_14,0x8, 0x8e);
    installInt(15,(unsigned long)intr_stub_15,0x8, 0x8e);
    installInt(16,(unsigned long)intr_stub_16,0x8, 0x8e);
    installInt(17,(unsigned long)intr_stub_17,0x8, 0x8e);
    installInt(18,(unsigned long)intr_stub_18,0x8, 0x8e);

    installInt(32,(unsigned long)mulTask,0x8, 0x8e);
    installInt(33,(unsigned long)intr_stub_33,0x8, 0x8e);
    installInt(34,(unsigned long)intr_stub_34,0x8, 0x8e);
    installInt(35,(unsigned long)intr_stub_35,0x8, 0x8e);
    installInt(36,(unsigned long)intr_stub_36,0x8, 0x8e);
    installInt(37,(unsigned long)intr_stub_37,0x8, 0x8e);
    installInt(38,(unsigned long)intr_stub_38,0x8, 0x8e);
    installInt(39,(unsigned long)intr_stub_39,0x8, 0x8e);
    installInt(40,(unsigned long)intr_stub_40,0x8, 0x8e);
    installInt(41,(unsigned long)intr_stub_41,0x8, 0x8e);
    installInt(42,(unsigned long)intr_stub_42,0x8, 0x8e);
    installInt(43,(unsigned long)intr_stub_43,0x8, 0x8e);
    installInt(44,(unsigned long)intr_stub_44,0x8, 0x8e);
    installInt(45,(unsigned long)intr_stub_45,0x8, 0x8e);
    installInt(46,(unsigned long)intr_stub_46,0x8, 0x8e);
    installInt(47,(unsigned long)intr_stub_47,0x8, 0x8e);
    installInt(48,(unsigned long)intr_stub_48,0x8, 0x8e);

asm("lidt %0" : : "g" (idtp));

    // Master-PIC
    outb(0x20, 0x11);
    outb(0x21, 0x20);
    outb(0x21, 0x04);
    outb(0x21, 0x01);

    // Slave-PIC initialisieren
    outb(0xa0, 0x11);
    outb(0xa1, 0x28);
    outb(0xa1, 0x02);
    outb(0xa1, 0x01);

    // Alle IRQs aktivieren (demaskieren)
    outb(0x20, 0x0);
    outb(0xa0, 0x0);

    //enableInterrupts();
}
